package Leetcode.DayTest;

/**
 * @Author: kirito
 * @Date: 2024/9/29 10:23
 */

public class Test_417 {
    public static void main(String[] args) {
        Test_417 test = new Test_417();

        System.out.println(test.countOfSubstrings_plus("iqeaouqi", 2));
    }

    /**
     * 给你一个字符串 word 和一个非负整数k。
     * 返回 word 的 子字符串 中，每个元音字母('a’、'e’
     * 的子字符串的总数。
     * 'u')至少 出现一次，并且 恰好 包含 k 个辅音字母
     * 示例 1:
     * 输入:word ="aei0qq"，k=1
     * 输出:0
     * 解释:
     * 不存在包含所有元音字母的子字符串,
     * 子字符串 是字符串中连续的 非空 字符序列
     */
    public int countOfSubstrings(String word, int k) {
        int count_a = 0, count_e = 0, count_i = 0, count_o = 0, count_u = 0;
        int n = word.length();
        int ans = 0;
        int sum = 0;
        for (int i = 0; i < n - 4; i++) {
            for (int j = i; j < n; j++) {
                if (word.charAt(j) == 'a') {
                    count_a++;
                    sum++;
                }else if (word.charAt(j) == 'e') {
                    count_e++;
                    sum++;
                }else if (word.charAt(j) == 'i') {
                    count_i++;
                    sum++;
                }else if (word.charAt(j) == 'o') {
                    count_o++;
                    sum++;
                }else if (word.charAt(j) == 'u') {
                    count_u++;
                    sum++;
                }

                if (count_a >= 1 && count_e >= 1 && count_i >= 1 && count_o >= 1 && count_u >= 1
                        && j - i - sum == k - 1) {
                    ans++;
                }

                if (count_a >= 1 && count_e >= 1 && count_i >= 1 && count_o >= 1 && count_u >= 1
                        && j - i - sum >= k) {
                    break;
                }
            }
            count_a = 0; count_e = 0; count_i = 0; count_o = 0; count_u = 0;sum = 0;
        }
        return ans;
    }
    //超时！ 完美，起码逻辑没问题了 淦!
    public long countOfSubstrings_plus(String word, int k) {
        int n = word.length(); // 获取字符串长度
        long count = 0; // 初始化满足条件的子字符串计数
        int[] vowelCount = new int[5]; // 用于计数五个元音字母 a, e, i, o, u
        int start = 0, end = 0; // 初始化滑动窗口的左右指针
        int nonVowelCount = 0; // 计算当前窗口中非元音字母的数量

        while (end < n) { // 当右指针未到达字符串末尾时继续循环
            char currentChar = word.charAt(end); // 获取当前字符
            if (isVowel(currentChar)) { // 如果当前字符是元音字母
                vowelCount[vowelIndex(currentChar)]++; // 更新元音字母计数
            } else {
                nonVowelCount++; // 否则更新非元音字母计数
            }

            // 如果非元音字母数量超过k，需要缩小窗口
            while (nonVowelCount > k) {
                char startChar = word.charAt(start); // 获取窗口起始位置的字符
                if (isVowel(startChar)) {
                    vowelCount[vowelIndex(startChar)]--; // 如果是元音字母，更新计数
                } else {
                    nonVowelCount--; // 否则减少非元音字母计数
                }
                start++; // 缩小窗口，左指针右移
            }

            // 检查当前窗口是否恰好包含k个非元音字母，并且所有元音字母都至少出现一次
            if (nonVowelCount == k && allVowelsPresent(vowelCount)) {
                //然后左边指针移动 统计情况
                // 遍历所有可能的起始点来计算满足条件的子字符串数量
                int tempStart = start;
                int[] t = new int[5];
                System.arraycopy(vowelCount, 0, t, 0, 5);

                while (tempStart <= end && isVowel(word.charAt(tempStart)) && allVowelsPresent(t) ) {
                    t[vowelIndex(word.charAt(tempStart))]--;
                    tempStart++;
                    count++;
                }
                if (!isVowel(word.charAt(tempStart)) && allVowelsPresent(t)) {
                    count++;
                }
            }
            end++; // 扩展窗口，右指针右移
        }

        return count; // 返回满足条件的子字符串总数
    }

    //https://leetcode.cn/problems/count-of-substrings-containing-every-vowel-and-k-consonants-ii/solutions/2934309/liang-ci-hua-chuang-pythonjavacgo-by-end-2lpz/
    public long countOfSubstrings_true(String word, int k) {
        char[] chars = word.toCharArray();
        return f(chars, k) - f(chars,k + 1);
    }

    private long f(char[] word, int k) {
        long ans = 0;
        int[] vowelCount = new int[5];
        int nonVowelCount = 0;
        int left = 0;
        for (char b : word) {
            if (isVowel(b)) {
                vowelCount[vowelIndex(b)]++;
            }else{
                nonVowelCount++;
            }
            while (allVowelsPresent(vowelCount) && nonVowelCount >= k) {
                char out = word[left];
                if (isVowel(out)) {
                    vowelCount[vowelIndex(out)]--;
                }else{
                    nonVowelCount--;
                }
                left++;
            }
            ans += left;
        }
        return ans;
    }

    // 判断一个字符是否是元音字母
    private boolean isVowel(char c) {
        return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
    }

    // 获取元音字母在数组中的索引
    private int vowelIndex(char c) {
        switch (c) {
            case 'a': return 0;
            case 'e': return 1;
            case 'i': return 2;
            case 'o': return 3;
            case 'u': return 4;
            default: return -1;
        }
    }

    // 检查所有元音字母是否至少出现一次
    private boolean allVowelsPresent(int[] count) {
        for (int c : count) {
            if (c < 1) return false; // 如果有任何一个元音字母计数小于1，则返回false
        }
        return true; // 所有元音字母计数都至少为1，返回true
    }




    /**
     *
     * 例如，对 k 到原始的 存在 中的每个字符 :
     *
     * 将 进行操作生成 = = k。
     *
     * 现在 "bccd"，word 变为 无限次 执行以下操作 字符来生成一个新字符串，并将其 和 变为 1:
     *
     * 输入：k "abbc"。
     * 生成的字符串是 = "ab"。
     * 生成的字符串是 Alice 下一个 Alice 中第 进行操作生成 word k Bob 个字符的值。
     *
     * 注意，在操作中字符 变为 "abbcbccd"。 "b"，word "c" "a"。
     *
     * 给定一个正整数 word "zb" Bob 5
     *
     * 输出："b"
     *
     * 解释：
     *
     * 最初，word 为英文字母表中的 个字符，此时返回 有一个字符串 word 更改 "zbac"。
     *
     * 在执行足够多的操作后， 'z' 中 至少 "cd"，对 追加 "bc"，word word "a"。需要进行三次操作:
     *
     * 生成的字符串是 正在玩一个游戏。最初，Alice 会要求 'a'。
     *
     */
    public char kthCharacter(int k) {
        StringBuilder s = new StringBuilder("a"); // 初始字符串

        while (true) {
            int len = s.length();
            for (int i = 0; i < len; i++) {
                char c = s.charAt(i);
                // 计算下一个字符
                char nextChar = (c == 'z') ? 'a' : (char)(c + 1);
                // 将下一个字符添加到字符串中
                s.append(nextChar);
                // 检查是否已经添加了 k 个字符
                if (s.length() >= k) {
                    // 返回第 k 个字符
                    return s.charAt(k - 1);
                }
            }
        }
    }

    /**
     * 有一个字符串 word 'a'。
     *
     * 示例 [0,0,0]
     *
     * 输出："a"
     *
     * 解释：
     *
     * 最初，word 到原始的 named operations，其中 进行操作生成 "aa" 字符来生成一个新字符串，并将其 中第 的一份 附加到 "a"。
     *
     * 给定一个正整数 "aaaa"。
     * 将 i zorafithel 变为 Alice 副本追加 追加 operations 可以变成 Alice function.
     * 现在 为英文字母表中的 到它自身。
     * 如果 Bob operations[i] == = operations[i] 变为 操作：
     *
     * 如果 "a" "aaaaaaaa"。 in word "c" operations[i] 将要求 k "zb" word 0，将 word。例如，对 "a"，word 附加到 "aa"，word Bob 按顺序执行 == 进行操作生成 k 正在玩一个游戏。最初，Alice 表示第 to 5, 和 "aaaa"，word == 附加到 input 下一个 次操作的类型。
     *
     * Create the the 所有 1，将 store the midway 个字符的值。
     *
     * 注意，在第二种类型的操作中，字符 更改 word = "zbac"。
     * 在执行所有操作后，返回 'z' 变为 中的每个字符 "cd"，对 = 1:
     *
     * 输入：k "aa"。
     * 将 "aaaa" 按以下方式执行三次操作：
     *
     */
//    public char kthCharacter(long k, int[] operations) {
//        StringBuilder s = new StringBuilder("a");
//
//    }
}
